home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / QuickTime / QuickTime VR / Make QTVR Panorama / CUtils.cp < prev    next >
Encoding:
Text File  |  2000-09-28  |  11.3 KB  |  559 lines  |  [TEXT/CWIE]

  1. /*
  2.     Random and sundry error, file and path name utilities
  3.     
  4.     Created 29 Jan 1996 by EGH
  5.     
  6.     Copyright © 1996, Apple Computer, Inc. All rights reserved.
  7. */
  8.  
  9. #include <FixMath.h>
  10. #include <fp.h>
  11.  
  12. #include <stdio.h>
  13. #include <String_Utils.h>
  14.  
  15. #include "CApp.h"
  16.  
  17. #include "CUtils.h"
  18.  
  19. /* GetFullPathName
  20.  
  21.     Get the full path name of the passed file, but force its length to fit into maxSize.
  22.     It is obviously more desirable to not restrict its length, but in this case we desire
  23.     this and "elipsize" the string by removing characters from the center.
  24. */
  25. void GetFullPathName(
  26.     const FSSpec *fileSpec,
  27.     Str255 outPathName,
  28.     short maxSize)
  29. {
  30.         // force an upper limit to what will fit in a Str255
  31.     if (maxSize > sizeof (Str255) - 1)
  32.         maxSize = sizeof (Str255) - 1;
  33.     
  34.     Int16 pathLen;
  35.     Handle pathH;
  36.     OSErr err = FSpGetFullPath(fileSpec, &pathLen, &pathH);
  37.     if (err == noErr)
  38.     {
  39.         ElipsedPathNameH(pathH, maxSize, outPathName, '…');
  40.         ::DisposeHandle(pathH);
  41.     }
  42.     else
  43.     {
  44.             // no memory (?!) so just copy the file's name
  45.         CopyPStr(fileSpec->name, outPathName);
  46.     }
  47. }
  48.  
  49. /* FSpGetFullPath
  50.  
  51.     Grok the full the path name of the passed file.
  52.     Nabbed from More Files 1.4.1 from my colleagues at Apple Developer Technical Support.
  53. */
  54. OSErr FSpGetFullPath(
  55.     const FSSpec *spec,
  56.     short *fullPathLength,
  57.     Handle *fullPath)
  58. {
  59.     OSErr        result;
  60.     FSSpec        tempSpec;
  61.     CInfoPBRec    pb;
  62.     
  63.     /* Make a copy of the input FSSpec that can be modified */
  64.     BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
  65.     
  66.     if ( tempSpec.parID == fsRtParID )
  67.     {
  68.         /* The object is a volume */
  69.         
  70.         /* Add a colon to make it a full pathname */
  71.         ++tempSpec.name[0];
  72.         tempSpec.name[tempSpec.name[0]] = ':';
  73.         
  74.         /* We're done */
  75.         result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
  76.     }
  77.     else
  78.     {
  79.         /* The object isn't a volume */
  80.         
  81.         /* Put the object name in first */
  82.         result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
  83.         if ( result == noErr )
  84.         {
  85.             /* Get the ancestor directory names */
  86.             pb.dirInfo.ioNamePtr = tempSpec.name;
  87.             pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
  88.             pb.dirInfo.ioDrParID = tempSpec.parID;
  89.             do    /* loop until we have an error or find the root directory */
  90.             {
  91.                 pb.dirInfo.ioFDirIndex = -1;
  92.                 pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
  93.                 result = PBGetCatInfoSync(&pb);
  94.                 if ( result == noErr )
  95.                 {
  96.                     /* Append colon to directory name */
  97.                     ++tempSpec.name[0];
  98.                     tempSpec.name[tempSpec.name[0]] = ':';
  99.                     
  100.                     /* Add directory name to beginning of fullPath */
  101.                     (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], tempSpec.name[0]);
  102.                     result = MemError();
  103.                 }
  104.             } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
  105.         }
  106.     }
  107.     if ( result == noErr )
  108.     {
  109.         /* Return the length */
  110.         *fullPathLength = GetHandleSize(*fullPath);
  111.     }
  112.     else
  113.     {
  114.         /* Dispose of the handle and return NULL and zero length */
  115.         DisposeHandle(*fullPath);
  116.         *fullPath = NULL;
  117.         *fullPathLength = 0;
  118.     }
  119.     
  120.     return result;
  121. }
  122.  
  123.  
  124. /* ElipsedPathNameH
  125.     
  126.     Gracefully degrade the passed string by removing characters from the center
  127.     until it fits into the passed maximum width. Inserts an elipsis character to indicate this.
  128. */
  129. void ElipsedPathNameH(
  130.     Handle pathNameH,
  131.     short maxWidth,
  132.     Str255 elipsedName,
  133.     char elipsis)
  134. {
  135.     long pNameLen = GetHandleSize(pathNameH);
  136.     char saveState = HGetState(pathNameH);
  137.     Ptr pathNameP = *pathNameH;
  138.  
  139.     HLock(pathNameH);
  140.  
  141.     if ((pNameLen <= 255) && (TextWidth(pathNameP, 0, (short)pNameLen) <= maxWidth))
  142.     {
  143.         BlockMove(pathNameP, (Ptr)(elipsedName + 1), pNameLen);
  144.         *elipsedName = (char)pNameLen;
  145.     }
  146.     else
  147.     {
  148.         long i, j, width = CharWidth(elipsis);
  149.         char rightChars[128];
  150.  
  151.         maxWidth /= 2;
  152.  
  153.         for (i = 1; (i < pNameLen) && (i < 128); i++)
  154.         {
  155.             char nextChar = pathNameP[i - 1];
  156.  
  157.             width += CharWidth(nextChar);
  158.             if (width >= maxWidth) break;
  159.             elipsedName[i] = nextChar;
  160.         }
  161.  
  162.         width = 0;
  163.         for (j = pNameLen - 1, *rightChars = 0; (j > i) && (*rightChars < 128); j--)
  164.         {
  165.             char nextChar = pathNameP[j];
  166.  
  167.             width += CharWidth(nextChar);
  168.             if (width >= maxWidth) break;
  169.             rightChars[++*rightChars] = nextChar;
  170.         }
  171.  
  172.         elipsedName[(*elipsedName = (char)i)] = elipsis;
  173.  
  174.         while (*rightChars)
  175.         {
  176.             elipsedName[++*elipsedName] = rightChars[(*rightChars)--];
  177.         }
  178.     }
  179.  
  180.     HSetState(pathNameH, saveState);
  181. }
  182.  
  183.  
  184. /* ElipsedPathName
  185.  
  186.     Same as ElipsedPathNameH except uses Str255's rather than a handle.
  187. */
  188. void ElipsedPathName(
  189.     Str255 pathName,
  190.     short maxWidth,
  191.     Str255 elipsedName,
  192.     char elipsis)
  193. {
  194.     Int16 pNameLen = pathName[0];
  195.     UInt8 *pathNameP = &pathName[1];
  196.     Int16 textWidth;
  197.     
  198.     textWidth = ::StringWidth(pathName);
  199.     if ((pNameLen <= 255) && (textWidth <= maxWidth))
  200.     {
  201.         BlockMove(pathNameP, (Ptr)(elipsedName + 1), pNameLen);
  202.         *elipsedName = (char)pNameLen;
  203.     }
  204.     else
  205.     {
  206.         long i, j, width = CharWidth(elipsis);
  207.         char rightChars[128];
  208.  
  209.         maxWidth /= 2;
  210.  
  211.         for (i = 1; (i < pNameLen) && (i < 128); i++)
  212.         {
  213.             char nextChar = pathNameP[i - 1];
  214.  
  215.             width += CharWidth(nextChar);
  216.             if (width >= maxWidth) break;
  217.             elipsedName[i] = nextChar;
  218.         }
  219.  
  220.         width = 0;
  221.         for (j = pNameLen - 1, *rightChars = 0; (j > i) && (*rightChars < 128); j--)
  222.         {
  223.             char nextChar = pathNameP[j];
  224.  
  225.             width += CharWidth(nextChar);
  226.             if (width >= maxWidth) break;
  227.             rightChars[++*rightChars] = nextChar;
  228.         }
  229.  
  230.         elipsedName[(*elipsedName = (char)i)] = elipsis;
  231.  
  232.         while (*rightChars)
  233.         {
  234.             elipsedName[++*elipsedName] = rightChars[(*rightChars)--];
  235.         }
  236.     }
  237. }
  238.  
  239.  
  240. /* SetSizedDescriptor
  241.     
  242.     Set the descriptor of the passed pane, but gracefully degrade the
  243.     length of the string to physically fit into the pane's frame.
  244. */
  245. void SetSizedDescriptor(
  246.     LWindow *parent,
  247.     PaneIDT inPaneID,
  248.     StringPtr inDescStr)
  249. {
  250.     LCaption *pane = (LCaption *)parent->FindPaneByID(inPaneID);
  251.     pane->FocusDraw(); // just to be in a valid port
  252.     ResIDT texttraitsID = pane->GetTextTraitsID();
  253.     UTextTraits::SetPortTextTraits(texttraitsID);
  254.     SDimension16 panesize;
  255.     pane->GetFrameSize(panesize);
  256.     Str255 elipStr;
  257.     ::ElipsedPathName(inDescStr, panesize.width, elipStr, '…');
  258.     pane->SetDescriptor(elipStr);
  259. }
  260.  
  261.  
  262. /* ReportError
  263.  
  264.     Report an error to the user.
  265. */
  266. void ReportError(
  267.     ExceptionCode inErr,
  268.     Int16 inStrIndex)
  269. {
  270.     Str255
  271.         errStr = "\pAn error occurred.",
  272.         errNumStr,
  273.         errDescStr;
  274.     Int16 descIndex;
  275.     
  276.     gApp->BugUserTilSwitchedIn();
  277.     
  278.         // make some attempt to provide a description of the error
  279.     switch (inErr)
  280.     {
  281.         case iMemFullErr:
  282.             descIndex = err_NotEnufMemory;
  283.             break;
  284.             
  285.         case notEnoughMemoryErr:
  286.             descIndex = err_NotEnufPhysicalMemory;
  287.             break;
  288.         
  289.         case dirFulErr:
  290.         case dskFulErr:
  291.             descIndex = err_DiskFull;
  292.             break;
  293.         
  294.         case ioErr:
  295.         case fnOpnErr:
  296.         case eofErr:
  297.         case fnfErr:
  298.         case nsvErr:
  299.             descIndex = err_DiskError;
  300.             break;
  301.         
  302.         case resNotFound:
  303.             descIndex = err_NoResource;
  304.         
  305.         default:
  306.             descIndex = err_NoDescription;
  307.     }
  308.     ::GetIndString(errDescStr, STRx_ErrorDescs, descIndex);
  309.     
  310.     ::SetCursor(&qd.arrow);
  311.     
  312.     ::GetIndString(errStr, STRx_Errors, inStrIndex);
  313.     ::NumToString(inErr, errNumStr);
  314.     ::ParamText(errStr, errNumStr, errDescStr, "\p");
  315.     ::StopAlert(ALRT_Error, nil);
  316. }
  317.  
  318.  
  319. OSErr GetFileParent(
  320.     FSSpec *fileSpec,
  321.     FSSpec *parentSpec)
  322. {
  323.     CInfoPBRec pBlock;
  324.     OSErr result;
  325.     
  326.     pBlock.dirInfo.ioVRefNum = fileSpec-> vRefNum;
  327.     pBlock.dirInfo.ioDrDirID = fileSpec-> parID;
  328.     pBlock.dirInfo.ioNamePtr = parentSpec-> name;
  329.     parentSpec-> name[0] = 0;
  330.     pBlock.dirInfo.ioFDirIndex = -1;
  331.      
  332.     result = PBGetCatInfoSync(&pBlock);
  333.     
  334.     if (result == noErr)
  335.     {
  336.         parentSpec-> vRefNum = fileSpec-> vRefNum;
  337.         parentSpec-> parID = pBlock.dirInfo.ioDrParID;
  338.     }
  339.     
  340.     return result;
  341. }
  342.  
  343.  
  344. const Int32 kPictFileHeaderSize = 512;
  345.  
  346. #pragma options align=mac68k
  347.  
  348. typedef struct PICT2Xheader {
  349.     short    version;
  350.     short    reserved;
  351.     Fixed    hRes;
  352.     Fixed    vRes;
  353.     Rect    srcRect;
  354.     long     reserved2;
  355. } PICT2Xheader;
  356.  
  357. #pragma options align=reset
  358.  
  359. /* ReadPictFrame
  360.  
  361.     Read a pict's rectangle.
  362. */
  363. void ReadPictFrame(
  364.     const FSSpec &inPictSpec,
  365.     Rect &outPictRect)
  366. {
  367.     LFile pictFile(inPictSpec);
  368.     
  369.     pictFile.OpenDataFork(fsRdPerm); // LFile will close the file upon failure
  370.     
  371.         // picture begins past the header
  372.     OSErr result = ::SetFPos(pictFile.GetDataForkRefNum(), fsFromStart, kPictFileHeaderSize);
  373.     ThrowIfOSErr_(result);
  374.     
  375.         // read a PICT2Xheader structure at 16 bytes into the pict
  376.     char pict[sizeof (PICT2Xheader) + 16];
  377.     Int32 count = sizeof (PICT2Xheader) + 16;
  378.     result = ::FSRead(pictFile.GetDataForkRefNum(), &count, &pict);
  379.     ThrowIfOSErr_(result);
  380.     
  381.     PICT2Xheader *pic2XHeader;
  382.     pic2XHeader = (PICT2Xheader *)&(((Ptr)(pict))[16]);
  383.     if (pic2XHeader->version == -2)
  384.     { // extended type 2
  385.         outPictRect = pic2XHeader->srcRect;
  386.     }
  387.     else
  388.         outPictRect = ((Picture *)pict)->picFrame;
  389.     
  390.     pictFile.CloseDataFork();
  391. }
  392.  
  393.  
  394. void FixedToStr(
  395.     Fixed inFixValue,
  396.     Str255 outStr)
  397. {
  398.         // convert to double_t, then use the dec routines
  399.     double_t value = Fix2X(inFixValue);
  400.     decform f;
  401.     f.style = FIXEDDECIMAL;
  402.     f.digits = 1;
  403.     decimal dec;
  404.     num2dec(&f, value, &dec);
  405.     dec2str(&f, &dec, (char *)outStr);
  406.     c2pstr((char *)outStr);
  407.     
  408.         // alternate method using the std C lib
  409.     //sprintf((char *)outStr, "%.1lf", value);
  410.     //c2pstr((char *)outStr);
  411. }
  412.  
  413.  
  414. Fixed StrToFixed(
  415.     StringPtr str)
  416. {
  417.     Fixed theNum;
  418.     long lower,upper;
  419.     short len,i,j, decPoint;
  420.     float fraction;
  421.     Boolean    neg;
  422.     
  423.     len = str[0];
  424.     
  425.     for (i=1; i<= len; i++)
  426.         if (str[i] == '.')
  427.             break;
  428.         // No decimal point
  429.     if (i >= len)
  430.     {
  431.         StringToNum(str, &theNum);
  432.         return (theNum << 16);
  433.     }
  434.     
  435.         // Make into two strings
  436.     decPoint = i;
  437.     str[0] = i-1;
  438.     str[decPoint] = len-i;
  439.     
  440.     StringToNum((StringPtr) str, &upper);
  441.     if ((neg = (int)(upper < 0)) != 0)
  442.         upper = - upper;
  443.     StringToNum((StringPtr) str+decPoint, &lower);
  444.     
  445.     fraction = lower;
  446.     for (j = 1; j <= (len-i) ; j++)
  447.         fraction = fraction / 10;
  448.     
  449.     lower = fraction * 0x10000;
  450.     
  451.         // Restore orig string
  452.     str[0] = len;
  453.     str[decPoint] = '.';
  454.  
  455.     return ((neg?-1:1)*((upper << 16) + lower));
  456. }
  457.  
  458.  
  459. /* FindCodecName
  460.  
  461.     Search the list of codecs for a name describing the passed codec.
  462. */
  463. Boolean FindCodecName(
  464.     StringPtr outName,
  465.     CodecType inCodec)
  466. {
  467.     Boolean found = false;
  468.     
  469.     CodecNameSpecListPtr cnsp;
  470.     OSErr result = ::GetCodecNameList(&cnsp, 1);
  471.     if (result == noErr)
  472.     {
  473.         for (Int32 i = 0; i < cnsp->count; i++)
  474.         {
  475.             if (cnsp->list[i].cType == inCodec)
  476.             {
  477.                 found = true; // yay
  478.                 CopyPStr(cnsp->list[i].typeName, outName);
  479.                 break;
  480.             }
  481.         }
  482.         
  483.         ::DisposeCodecNameList(cnsp);
  484.     }
  485.     
  486.     return found;
  487. }
  488.  
  489.  
  490. /* SetCompressionText
  491.  
  492.     Set the passed pane's descriptor to text describing the passed image compression
  493.     settings.
  494. */
  495. void SetCompressionText(
  496.     LPane *inPane,
  497.     CodecType inCodec,
  498.     CodecQ inSpatialQuality)
  499. {
  500.     if (inPane != nil)
  501.     {
  502.             // attempt to find a name for the current codec
  503.         Str255 str;
  504.         if (!FindCodecName(str, inCodec))
  505.         {
  506.                 // put something in the string, however cryptic
  507.             str[0] = 7;
  508.             str[1] = '\'';
  509.             *(OSType *)&str[2] = inCodec;
  510.             str[6] = '\'';
  511.             str[7] = ' ';
  512.         }
  513.         else
  514.             str[++str[0]] = ' ';
  515.         
  516.             // create a description of the compression quality
  517.         Str255 qstr;
  518.         if (inSpatialQuality >= codecLosslessQuality)
  519.             CopyPStr("\pLossless", qstr);
  520.         else if (inSpatialQuality >= codecMaxQuality)
  521.             CopyPStr("\pMaximum", qstr);
  522.         else if (inSpatialQuality >= codecHighQuality)
  523.             CopyPStr("\pHigh", qstr);
  524.         else if (inSpatialQuality >= codecNormalQuality)
  525.             CopyPStr("\pNormal", qstr);
  526.         else if (inSpatialQuality > codecMinQuality)
  527.             CopyPStr("\pLow", qstr);
  528.         else
  529.             CopyPStr("\pMinimum", qstr);
  530.         ConcatPStr(str, qstr);
  531.  
  532.         ConcatPStr(str, "\p (");
  533.         ::NumToString((((((float)inSpatialQuality)+.5) / 1024.0) * 100), qstr);
  534.         ConcatPStr(str, qstr);
  535.         ConcatPStr(str, "\p)");
  536.         
  537.         inPane->SetDescriptor(str);
  538.     }
  539. }
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.